package com.cmos.um.utils;

import java.util.Map;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;

/**
 * 【类】与CC（之CTI模块）的Json接口——用于人员和呼叫的管理
 */
public class WSRequest
{
    /**
     * 【工具】 日志对象
     */
	private static Logger logger = Logger.getLogger(HttpClientUtil.class);

	/**
	 * 【工具】   向CC发出JSON请求并得到响应消息
	 * @param     url                CTI服务的URL地址（为null时会使用配置文件中cincc-ws参数值）
     * @param     operate            指示什么操作的URL地址
     * @param     params             请求消息中的参数集（放在params标签下的MAP对象）
     * @return    Map<String,Object> 返回数据（MAP）
     * @exception Exception          出问题时会抛出异常
     */
    public static Map<String,Object> _send(String url, String operate, JSONObject params) throws Exception
    {
        String s =null;

        //1 检查输入参数
        if(operate==null || !operate.matches("[0-9a-zA-Z/]+"))
        {
            String msg= "在向CC（之CTI模块）发送Json消息时，给出的操作operate（URL）地址格式不正确，给出的地址为“"+operate+"”";
            logger.error(msg);
            throw new Exception(msg);
        }
        if(params==null)
            params=new JSONObject(); // 可能确实没有参数

        //2 准备发出的参数
        String parent_string =null; // 数据
        {
            //a 准备发出的数据结构
//            JSONObject parent = new JSONObject();
//            parent.put("params", params);
            parent_string=params.toJSONString();

            //b 准备操作URL地址
            if(url==null)
                url= PropertiesUtil.getString("cincc-ws");
            if(url==null || !url.startsWith("http://"))
            {
                String msg= "在 system.properties 配置文件中没有设置“cinc-ws”配置项——对CC的JSON接口服务所在的URL地址，或设置的URL地址格式有误，目前配置的此地址为｛"+url+"｝";
                logger.error(msg);
                throw new Exception(msg);
            }

            if(url.endsWith("/") && operate.startsWith("/")) url += operate.substring(1);
            else                                             url += operate;
        }

        //3 发出消息
        String result_string =null; // 返回的消息体（字符串）
        try
        {
            result_string= (new simpleSQL()).httpPost_Json(url,parent_string);
        }
        catch(Exception e)
        {
            String msg= "向CC（之CTI模块）发送Http消息失败，c发送的数据为："+parent_string+e.getMessage();
            logger.error(msg);
            throw new Exception(msg);
        }

        //4 整理结果
        Map<String,Object> result = null;
        try
        {
            result= DataUtil.json2Map(result_string);

            if(result==null    ) throw new Exception("解析的结果为空null");
            if(result.isEmpty()) throw new Exception("解析的结果为空字符串");
        }
        catch(Exception e)
        {
            String msg= "向CC（之CTI模块）发送Http消息后，解析CC返回的JSON字符串失败，"+e.getMessage()+"，向 "+url+" 发出的消息为｛"+parent_string+"｝，从CC收到的字符串为“"+result_string+"”";
            logger.error(msg);
            throw new Exception(msg);
        }

        //5 检查CC返回会的状态
        if (!result.get("rescode").toString().equals("0"))
        {
            String msg= "CC（之CTI模块）返回“操作失败”，具体原因为："+result.get("rtnMsg").toString()+"。向 "+url+" 发出的消息为｛"+parent_string+"｝，从CC收到的字符串为“"+result_string+"”";
            logger.error(msg);
            throw new Exception(msg);
        }

        //6 调试信息
        /*DEBUG*/ logger.debug("CIN-CC-JSON操作（"+url+"）："+parent_string+" 》》》》》"+result_string);

        //7 函数正常结束
        return result;
    }

    //-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-//

    /**
     * 【方法】   发送并得到回应——通用的方法
     * @param     operate   指示什么操作的URL地址
     * @param     params    主要参数集（放在params标签下的MAP对象）
     * @return    Object    得到的结果——对于结果含bean 字段的，返回MAP<String,Object>，
     *                                ——对于结果含beans字段的，返回List<MAP<String,Object>>
     *                                ——没有返回结果或结果为空的，返回null
     * @exception Exception 出问题时会抛出异常
     */
    public static Object send(String operate, JSONObject params) throws Exception
    {
        return send(null,operate,params);
    }

    /**
     * 【方法】   发送并得到回应——通用的方法
     * @param     ip        CTI服务器的IP地址
     * @param     operate   指示什么操作的URL地址
     * @param     params    主要参数集（放在params标签下的MAP对象）
     * @return    Object    得到的结果——对于结果含bean 字段的，返回MAP<String,Object>，
     *                                ——对于结果含beans字段的，返回List<MAP<String,Object>>
     *                                ——没有返回结果或结果为空的，返回null
     * @exception Exception 出问题时会抛出异常
     */
    public static Object send(String ip, String operate, JSONObject params) throws Exception
    {
        Object X =null;

        //1 转化IP地址为URL
        String url =null;
        if(ip!=null) url= "http://"+((ip.indexOf(":")>=0)?(ip):(ip+":14200"));
        //else         url= PropertiesUtil.getString("cincc-ws");

        //2 向CC发出消息并获得回应MAP
        Map<String,Object> M= _send(url,operate,params);

        //3 解析MAP中的主要返回参数
        Object result =null;
        try
        {
                 if((X=M.get("bean" ))!=null && !X.toString().isEmpty())  result= DataUtil.json2Map (X);
            else if((X=M.get("beans"))!=null && !X.toString().isEmpty())  result= DataUtil.json2List(X);
            else if((X=M.get("output"))!=null &&!X.toString().isEmpty()) result = DataUtil.json2Map(X);//在读取任务信息是返回的内容
                 else if((X=M.get("rescode"))!=null &&!X.toString().isEmpty()) result = X;//在读取任务信息是返回的内容
                 else                                                          result= null                 ;
        }
        catch(Exception e)
        {
            String msg= "将CC（之CTI模块）对请求的返回数据转化为MAP或LIST对象时出现异常，"+e.getMessage()+"，向 "+operate+" 发出的消息为“"+params.toJSONString()+"”，CC返回的消息为｛"+M.toString()+"｝";
            logger.error(msg);
            throw new Exception(msg);
        }

        //4 函数正常结束，返回解析后的参数
        return result;
    }

    /**
	 * 【方法】   设置（已过时，请使用send函数来代替）
	 * @param     operate   指示什么操作的URL地址
	 * @param     params    主要参数集（放在params标签下的MAP对象）
	 * @return    boolean   是否成功——此处为兼容而保留，实际上只返回true
	 * @exception Exception 出问题时会抛出异常
	 */
	public static boolean setDataFromWS(String operate, JSONObject params) throws Exception
	{
	    send(operate,params);
	    return true;
    }

    /**
     * 【方法】   获取（已过时，请使用send函数来代替）
     * @param     operate   指示什么操作的URL地址
     * @param     params    主要参数集（放在params标签下的MAP对象）
     * @return    Object    得到的结果——对于结果含bean 字段的，返回MAP<String,Object>，
     *                                ——对于结果含beans字段的，返回List<MAP<String,Object>>
     *                                ——没有返回结果或结果为空的，返回null
     * @exception Exception 出问题时会抛出异常
     */
    public static Object getDataFromWS(String operate, JSONObject params) throws Exception
    {
        return send(operate,params);
    }

}
